package com.njegovanobradovic.core.dao;

import java.io.Serializable;
import java.util.List;

import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;

public class HibernateDAOImpl implements HibernateDAO{
	@Inject
    private Session session;

	public Session provideManager() {
		return session;
	}

	@SuppressWarnings("unchecked")
    public <T> List<T> get(Class<T> searchForType) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        return criteria.list();
    }
    
    @SuppressWarnings("unchecked")
    public <T> List<T> get(Class<T> searchForType, int firstResult, int maxResults) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        criteria.setFirstResult(firstResult);
        criteria.setMaxResults(maxResults);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    public <T> T get(Serializable id, Class<T> searchForType) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        criteria.add(Restrictions.idEq(id)).setMaxResults(1);
        return (T)criteria.list().get(0);
    }
    
    @SuppressWarnings("unchecked")
    public <T> T getByIntValue(Class<T> searchForType, String property, int value) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        return (T) criteria.add(Restrictions.eq(property, value)).uniqueResult();
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> get(Class<T> searchForType, T example) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        criteria.add(Example.create(example));
        return criteria.list();
    }
    
    @SuppressWarnings("unchecked")
    public <T> List<T> get(Class<T> searchForType, T example, int firstResult, int maxResults) {
        Session session = provideManager();
        Criteria criteria = session.createCriteria(searchForType);
        criteria.add(Example.create(example));
        criteria.setFirstResult(firstResult);
        criteria.setMaxResults(maxResults);
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
	public <T> List<T> get(T example) {
        return get((Class<T>)example.getClass(), example);
    }

    @SuppressWarnings("unchecked")
	public <T> List<T> get(T example, int firstResult, int maxResults) {
        return get((Class<T>)example.getClass(), example, firstResult, maxResults);
    }

    public void save(Object object) {
        Session session = provideManager();
        session.saveOrUpdate(object); 
    }

    public void delete(Object object) {
        Session session = provideManager();
        session.delete(object);
    }

    public <T> void delete(Serializable id, Class<T> searchForType) {
        Object toBeDeleted = get(id,searchForType);
        delete(toBeDeleted);
    }

    public void deleteAll(Class clazz) {
        Session session = provideManager();
        session.delete("from " + clazz.getName());
    }

    public void flush() {
       Session session = provideManager();
       session.flush();
    }

}
